# -*- mode: python -*-
###
#
# (c) 2000-2007 Wijnand Modderman <wijnand at tehmaze dot com>
# All rights reserved. See docs/LICENSE
#
###

__revision__ = '$Hg: whois.py,v 81bdaf04466a 2007/01/21 04:12:26 +0100 $'

# system imports
import re
import socket

# DDB imports
from ddb.tools import syntax

# Twisted imports
from twisted.internet import reactor, protocol

# DDB exports
EXPORT=['Whois']

class WhoisClient(protocol.Protocol):
    """Once connected, send a message, then print the result."""
    reply = ''    

    def connectionMade(self):
        self.transport.write(self.factory.event.args + "\r\n")
    
    def dataReceived(self, data):
        "As soon as any data is received, write it back."
        self.reply += data
    
    def connectionLost(self, reason):
        self.factory.callback(self.factory.event, self.reply)

class WhoisFactory(protocol.ClientFactory):
    protocol = WhoisClient

    def __init__(self, event, callback, errback):
        self.callback = callback
        self.errback  = errback
        self.event    = event

    def clientConnectionFailed(self, connector, reason):
        print "Connection failed - goodbye!"
    
    def clientConnectionLost(self, connector, reason):
        print "Connection lost - goodbye!"


class Whois:
    _defaults = {
        re.compile('^\d+.\d+\.\d+\.\d+$'): "whois.arin.net",
        re.compile('.'): "whois.internic.com"
    }

    def whois(self, event):
        """<query>

        Query can be:
            [AS]<number>    to lookup AS-numbers,
            <dotted quad>   to lookup IP-numbers,
            <domain>        to lookup domains,
            <handle>        to lookup registry handles
        """
        if not event.args:
            return event.reply(syntax())
        w = WhoisFactory(event, self._whois, self._whoisError)
        # Look in defaults lookup table
        for (matcher, server) in WHOISMAP.iteritems():
            if matcher.search(event.args):
                event.reply('Querying %s ...' % server)
                reactor.connectTCP(server, 43, w)
                return
        # Fallback table
        for (matcher, server) in self._defaults.iteritems():
            if matcher.search(event.args):
                event.reply('Querying to fallback %s ...' % server)
                reactor.connectTCP(server, 43, w)
                return
        event.reply('No suitable whois server for you request was found')

    def _whois(self, event, reply):
        # cleanup
        while '  ' in reply:
            reply = reply.replace('  ', ' ')
        lines = [x.strip() for x in reply.strip().splitlines()]
        lines = [x for x in lines if not x.startswith('%') and x]
        event.reply(', '.join(lines))

    def _whoisError(self, event, reason):
        pass

def whoisMapRe(map):
    out = {}
    for (regexp, value) in map.iteritems():
        out[re.compile(regexp)] = value
    return out

class ipMatch:
    _bit2mask = [
        "0.0.0.0",
        "128.0.0.0",       "192.0.0.0",       "224.0.0.0",       "240.0.0.0",
        "248.0.0.0",       "252.0.0.0",       "254.0.0.0",       "255.0.0.0",
        "255.128.0.0",     "255.192.0.0",     "255.224.0.0",     "255.240.0.0",
        "255.248.0.0",     "255.252.0.0",     "255.254.0.0",     "255.255.0.0",
        "255.255.128.0",   "255.255.192.0",   "255.255.224.0",   "255.255.240.0",
        "255.255.248.0",   "255.255.252.0",   "255.255.254.0",   "255.255.255.0",
        "255.255.255.128", "255.255.255.192", "255.255.255.224", "255.255.255.240",
        "255.255.255.248", "255.255.255.252", "255.255.255.254", "255.255.255.255",
    ]
    def __init__(self, subnet, mask):
        self.subnet = self.ip2Long(subnet)
        self.mask   = self.ip2Long(self._bit2mask[mask])

    def match(self, ip):
        print "match", self.subnet, self.mask, ip
        try:
            return (self.ip2Long(ip)&self.mask) == self.subnet
        except:
            return False
       
    def search(self, ip):
        return self.match(ip)
 
    def ip2Long(self, data):
        data = map(int, data.split("."))
        result = 0L
        for i in data:
            result = (result<<8) | i
        return result

def whoisMapIPv4(map):
    # This must be horrible implementation
    out = {}
    for (subnet, value) in map.iteritems():
        (subnet, mask) = subnet.split('/', 1)
        out[ipMatch(subnet, int(mask))] = value
    return out 

#
# Taken from jwhois
#
_WHOIS_AS = {
    #
    # Catch AS numbers
    #
    "^[0-9]+$":     "whois.arin.net",
    "^ASN-.+":      "whois.arin.net",
    "^AS[0-9]+$":   "whois.radb.net",
    }
_WHOIS_IPV4 = {
    # Note: JPNIC doesn't appear to publish lists of netblocks on their
    #       website - this data was derived by searching for "Japan Network
    #       Information Center" in the ARIN and APNIC databases.  It may
    #       not be complete.
    "61.112.0.0/12": "whois.nic.ad.jp",    # APNIC JPNIC-NET-JP
    "61.192.0.0/12": "whois.nic.ad.jp",    # APNIC JPNIC-NET-JP
    "61.208.0.0/13": "whois.nic.ad.jp",    # APNIC JPNIC-NET-JP
    "133.0.0.0/8": "whois.nic.ad.jp",      # ARIN NETBLK-JAPANB-INET
    "150.100.0.0/16": "whois.nic.ad.jp",   # ARIN NETBLK-JAPAN2
    "150.1.0.0/16": "whois.nic.ad.jp",     # ARIN NETBLK-JAPAN2
    "150.16.0.0/12": "whois.nic.ad.jp",    # ARIN NETBLK-JAPAN2
    "150.2.0.0/15": "whois.nic.ad.jp",     # ARIN NETBLK-JAPAN2
    "150.32.0.0/11": "whois.nic.ad.jp",    # ARIN NETBLK-JAPAN2
    "150.4.0.0/14": "whois.nic.ad.jp",     # ARIN NETBLK-JAPAN2
    "150.64.0.0/11": "whois.nic.ad.jp",    # ARIN NETBLK-JAPAN2
    "150.8.0.0/13": "whois.nic.ad.jp",     # ARIN NETBLK-JAPAN2
    "150.96.0.0/14": "whois.nic.ad.jp",    # ARIN NETBLK-JAPAN2
    "158.198.0.0/15": "whois.nic.ad.jp",   # ARIN NETBLK-JAPAN-NET-1
    "158.200.0.0/13": "whois.nic.ad.jp",   # ARIN NETBLK-JAPAN-NET-1
    "158.208.0.0/13": "whois.nic.ad.jp",   # ARIN NETBLK-JAPAN-NET-1
    "158.216.0.0/15": "whois.nic.ad.jp",   # ARIN NETBLK-JAPAN-NET-1
    "163.130.0.0/15": "whois.nic.ad.jp",   # ARIN NETBLK-JAPAN-NET
    "163.132.0.0/14": "whois.nic.ad.jp",   # ARIN NETBLK-JAPAN-NET
    "163.136.0.0/13": "whois.nic.ad.jp",   # ARIN NETBLK-JAPAN-NET
    "163.144.0.0/14": "whois.nic.ad.jp",   # ARIN NETBLK-JAPAN-NET
    "163.148.0.0/15": "whois.nic.ad.jp",   # ARIN NETBLK-JAPAN-NET
    "192.218.0.0/16": "whois.nic.ad.jp",   # ARIN NETBLK-JAPANC-INET-BLOCK1
    "192.244.0.0/16": "whois.nic.ad.jp",   # ARIN NETBLK-JAPAN-INET-C
    "192.41.192.0/24": "whois.nic.ad.jp",  # ARIN NET-UTOKYO-CON1
    "192.47.0.0/17": "whois.nic.ad.jp",    # ARIN NETBLK-KIT-BLOCK
    "192.47.128.0/18": "whois.nic.ad.jp",  # ARIN NETBLK-KIT-BLOCK
    "192.47.142.0/24": "whois.nic.ad.jp",  # ARIN ITC-JP2
    "192.47.192.0/19": "whois.nic.ad.jp",  # ARIN NETBLK-KIT-BLOCK
    "192.47.224.0/20": "whois.nic.ad.jp",  # ARIN NETBLK-KIT-BLOCK
    "192.47.240.0/23": "whois.nic.ad.jp",  # ARIN NETBLK-KIT-BLOCK
    "192.51.128.0/17": "whois.nic.ad.jp",  # ARIN NETBLK-JAPANC-INET4
    "192.51.16.0/20": "whois.nic.ad.jp",   # ARIN NETBLK-JAPANC-INET4
    "192.51.32.0/19": "whois.nic.ad.jp",   # ARIN NETBLK-JAPANC-INET4
    "192.51.64.0/18": "whois.nic.ad.jp",   # ARIN NETBLK-JAPANC-INET4
    "202.11.0.0/16": "whois.nic.ad.jp",    # APNIC JPNIC-NET-JP
    "202.13.0.0/16": "whois.nic.ad.jp",    # APNIC JPNIC-NET-JP
    "202.15.0.0/16": "whois.nic.ad.jp",    # APNIC JPNIC-NET-JP
    "202.16.0.0/14": "whois.nic.ad.jp",    # APNIC JPNIC-NET-JP
    "202.23.0.0/16": "whois.nic.ad.jp",    # APNIC JPNIC-NET-JP
    "202.24.0.0/15": "whois.nic.ad.jp",    # APNIC JPNIC-NET-JP
    "202.26.0.0/16": "whois.nic.ad.jp",    # APNIC JPNIC-NET-JP
    "202.32.0.0/14": "whois.nic.ad.jp",    # APNIC JPNIC-NET-JP
    "202.48.0.0/16": "whois.nic.ad.jp",    # APNIC JPNIC-NET-JP
    "202.208.0.0/12": "whois.nic.ad.jp",   # APNIC JPNIC-NET-JP
    "202.224.0.0/11": "whois.nic.ad.jp",   # APNIC JPNIC-NET-JP
    "203.136.0.0/14": "whois.nic.ad.jp",   # APNIC JPNIC-NET-JP
    "203.140.0.0/15": "whois.nic.ad.jp",   # APNIC JPNIC-NET-JP
    "203.178.0.0/15": "whois.nic.ad.jp",   # APNIC JPNIC-NET-JP
    "203.180.0.0/14": "whois.nic.ad.jp",   # APNIC JPNIC-NET-JP
    "210.128.0.0/11": "whois.nic.ad.jp",   # APNIC JPNIC-NET-JP
    "210.136.0.0/13": "whois.nic.ad.jp",
    "210.160.0.0/12": "whois.nic.ad.jp",   # APNIC JPNIC-NET-JP
    "210.188.0.0/14": "whois.nic.ad.jp",   # APNIC JPNIC-NET-JP
    "210.196.0.0/14": "whois.nic.ad.jp",   # APNIC JPNIC-NET-JP
    "210.224.0.0/12": "whois.nic.ad.jp",   # APNIC JPNIC-NET-JP
    "210.248.0.0/13": "whois.nic.ad.jp",   # APNIC JPNIC-NET-JP
    "211.0.0.0/12": "whois.nic.ad.jp",     # APNIC JPNIC-NET-JP
    "211.16.0.0/14": "whois.nic.ad.jp",    # APNIC JPNIC-NET-JP
    "211.52.0.0/14": "whois.nic.or.kr",
    "211.56.0.0/13": "whois.nic.or.kr",
    "211.104.0.0/13": "whois.nic.or.kr",
    "211.112.0.0/13": "whois.nic.or.kr",
    "211.120.0.0/13": "whois.nic.ad.jp",   # APNIC JPNIC-NET-JP
    "211.128.0.0/13": "whois.nic.ad.jp",   # APNIC JPNIC-NET-JP
    "211.172.0.0/14": "whois.nic.or.kr",
    "211.176.0.0/12": "whois.nic.or.kr",
    "211.192.0.0/13": "whois.nic.or.kr",
    "219.96.0.0/11": "whois.nic.ad.jp",
    "220.104.0.0/13": "whois.nic.ad.jp",
    "220.208.0.0/12": "whois.nic.ad.jp",
    "221.112.0.0/13": "whois.nic.ad.jp",

    "24.132.0.0/16": "whois.ripe.net",
    "24.232.0.0/16": "whois.lacnic.net",
    "41.0.0.0/8": "whois.afrinic.net", 
    "43.0.0.0/8": "whois.v6nic.net",
    "58.0.0.0/8": "whois.apnic.net",
    "59.0.0.0/8": "whois.apnic.net",
    "60.0.0.0/8": "whois.apnic.net",
    "61.0.0.0/8": "whois.apnic.net",
    "62.135.36.0/17": "whois.afrinic.net",
    "62.0.0.0/8": "whois.ripe.net",
    "80.87.64.0/19": "whois.afrinic.net",
    "80.0.0.0/8": "whois.ripe.net",
    "81.91.224.0/20": "whois.afrinic.net",
    "81.192.0.0/16": "whois.afrinic.net",
    "81.0.0.0/8": "whois.ripe.net",
    "82.101.128.0/18": "whois.afrinic.net",
    "82.201.128.0/17": "whois.afrinic.net",
    "82.201.160.0/19": "whois.afrinic.net",
    "82.201.224.0/19": "whois.afrinic.net", 
    "82.0.0.0/8": "whois.ripe.net",
    "83.0.0.0/8": "whois.ripe.net",
    "84.36.0.0/17": "whois.afrinic.net",
    "84.0.0.0/8": "whois.ripe.net",
    "85.0.0.0/8": "whois.ripe.net",
    "86.0.0.0/8": "whois.ripe.net",
    "87.0.0.0/8": "whois.ripe.net",
    "88.0.0.0/8": "whois.ripe.net",
    "89.0.0.0/8": "whois.ripe.net",
    "90.0.0.0/8": "whois.ripe.net",
    "91.0.0.0/8": "whois.ripe.net", 
    "121.0.0.0/8": "whois.apnic.net",
    "122.0.0.0/8": "whois.apnic.net",
    "123.0.0.0/8": "whois.apnic.net",
    "124.0.0.0/8": "whois.apnic.net",
    "125.0.0.0/8": "whois.apnic.net",
    "126.0.0.0/8": "whois.apnic.net", 
    "129.132.0.0/16": "whois.ripe.net",
    "129.177.0.0/16": "whois.ripe.net",
    "129.187.0.0/16": "whois.ripe.net",
    "130.225.0.0/16": "whois.ripe.net",
    "130.226.0.0/15": "whois.ripe.net",
    "130.227.0.0/16": "whois.ripe.net",
    "130.228.0.0/14": "whois.ripe.net",
    "130.232.0.0/13": "whois.ripe.net",
    "130.240.0.0/14": "whois.ripe.net",
    "130.244.0.0/16": "whois.ripe.net",
    "130.244.0.0/16": "whois.ripe.net",
    "132.64.0.0/13": "whois.ripe.net",
    "132.72.0.0/14": "whois.ripe.net",
    "132.76.0.0/15": "whois.ripe.net",
    "132.78.0.0/16": "whois.ripe.net",
    "137.138.0.0/16": "whois.ripe.net",
    "138.130.0.0/16": "whois.apnic.net",
    "140.109.0.0/16": "whois.apnic.net",
    "140.110.0.0/15": "whois.apnic.net",
    "140.112.0.0/12": "whois.apnic.net",
    "140.116.0.0/14": "whois.apnic.net",
    "140.120.0.0/13": "whois.apnic.net",
    "140.128.0.0/13": "whois.apnic.net",
    "140.136.0.0/15": "whois.apnic.net",
    "140.138.0.0/16": "whois.apnic.net",
    "141.223.0.0/16": "whois.apnic.net",
    "143.89.0.0/16": "whois.apnic.net",
    "143.90.0.0/16": "whois.apnic.net",
    "144.130.0.0/15": "whois.apnic.net",
    "144.132.0.0/14": "whois.apnic.net",
    "144.136.0.0/14": "whois.apnic.net",
    "144.140.0.0/16": "whois.apnic.net",
    "145.0.0.0/8": "whois.ripe.net",
    "147.46.0.0/15": "whois.apnic.net",
    "150.1.0.0/16": "whois.apnic.net",
    "150.2.0.0/15": "whois.apnic.net",
    "150.4.0.0/14": "whois.apnic.net",
    "150.8.0.0/13": "whois.apnic.net",
    "150.16.0.0/12": "whois.apnic.net",
    "150.32.0.0/11": "whois.apnic.net",
    "150.64.0.0/11": "whois.apnic.net",
    "150.96.0.0/14": "whois.apnic.net",
    "150.100.0.0/15": "whois.apnic.net",
    "150.217.0.0/16": "whois.ripe.net",
    "151.3.0.0/16": "whois.ripe.net",
    "151.4.0.0/15": "whois.ripe.net",
    "151.10.0.0/15": "whois.ripe.net",
    "151.12.0.0/14": "whois.ripe.net",
    "151.16.0.0/12": "whois.ripe.net",
    "151.32.0.0/11": "whois.ripe.net",
    "151.64.0.0/11": "whois.ripe.net",
    "151.96.0.0/14": "whois.ripe.net",
    "151.100.0.0/16": "whois.ripe.net",
    "155.230.0.0/16": "whois.apnic.net",
    "158.190.0.0/15": "whois.ripe.net",
    "158.192.0.0/14": "whois.ripe.net",
    "158.196.0.0/15": "whois.ripe.net",
    "159.147.0.0/16": "whois.ripe.net",
    "159.148.0.0/15": "whois.ripe.net",
    "160.216.0.0/14": "whois.ripe.net",
    "160.220.0.0/16": "whois.ripe.net",
    "161.110.0.0/15": "whois.ripe.net",
    "161.112.0.0/16": "whois.ripe.net",
    "163.13.0.0/16": "whois.apnic.net",
    "163.14.0.0/15": "whois.apnic.net",
    "163.16.0.0/12": "whois.apnic.net",
    "163.32.0.0/16": "whois.apnic.net",
    "163.156.0.0/14": "whois.ripe.net",
    "163.160.0.0/12": "whois.ripe.net",
    "164.0.0.0/11": "whois.ripe.net",
    "164.32.0.0/13": "whois.ripe.net",
    "164.40.0.0/16": "whois.ripe.net",
    "164.100.0.0/16": "whois.apnic.net",
    "164.128.0.0/12": "whois.ripe.net",
    "164.160.0.0/14": "whois.apnic.net",
    "164.164.0.0/16": "whois.apnic.net",
    "165.21.0.0/16": "whois.apnic.net",
    "165.76.0.0/16": "whois.apnic.net",
    "165.165.0.0/16": "whois.afrinic.net",
    "165.228.0.0/15": "whois.apnic.net",
    "168.95.0.0/16": "whois.apnic.net",
    "168.126.0.0/16": "whois.apnic.net",
    "168.187.0.0/16": "whois.ripe.net",
    "169.208.0.0/16": "whois.apnic.net",
    "171.16.0.0/12": "whois.ripe.net",
    "171.32.0.0/15": "whois.ripe.net",
    "189.0.0.0/8": "whois.lacnic.net",
    "190.0.0.0/8": "whois.lacnic.net",
    "196.0.0.0/8": "whois.afrinic.net", 
    "192.16.192.0/24": "whois.ripe.net",
    "192.114.0.0/15": "whois.ripe.net",
    "192.116.0.0/15": "whois.ripe.net",
    "192.118.0.0/16": "whois.ripe.net",
    "192.140.1.0/24": "whois.ripe.net",
    "192.140.2.0/23": "whois.ripe.net",
    "192.140.4.0/22": "whois.ripe.net",
    "192.140.8.0/21": "whois.ripe.net",
    "192.140.16.0/20": "whois.ripe.net",
    "192.140.32.0/19": "whois.ripe.net",
    "192.140.64.0/18": "whois.ripe.net",
    "192.140.128.0/17": "whois.ripe.net",
    "192.141.0.0/16": "whois.ripe.net",
    "192.142.0.0/15": "whois.ripe.net",
    "192.144.0.0/16": "whois.ripe.net",
    "192.145.0.0/17": "whois.ripe.net",
    "192.145.128.0/18": "whois.ripe.net",
    "192.145.192.0/19": "whois.ripe.net",
    "192.145.224.0/22": "whois.ripe.net",
    "192.145.228.0/23": "whois.ripe.net",
    "192.145.230.0/24": "whois.ripe.net",
    "192.164.0.0/16": "whois.ripe.net",
    "193.0.0.0/8": "whois.ripe.net",
    "194.0.0.0/8": "whois.ripe.net",
    "195.166.224.0/19": "whois.afrinic.net",
    "195.0.0.0/8": "whois.ripe.net",
    "196.2.96.0/19": "whois.afrinic.net",
    "196.2.128.0/17": "whois.afrinic.net",
    "196.200.0.0/13": "whois.afrinic.net",
    "200.17.0.0/16": "whois.nic.br",
    "200.128.0.0/9": "whois.nic.br",
    "200.0.0.0/8": "whois.lacnic.net",
    "201.0.0.0/8": "whois.lacnic.net",
    "202.0.0.0/8": "whois.apnic.net",
    "203.0.0.0/8": "whois.apnic.net",
    "210.0.0.0/8": "whois.apnic.net",
    "211.0.0.0/8": "whois.apnic.net",
    "212.22.160.0/19": "whois.afrinic.net",
    "212.0.0.0/8": "whois.ripe.net",
    "213.136.96.0/19": "whois.afrinic.net",
    "213.154.64.0/19": "whois.afrinic.net",
    "213.0.0.0/8": "whois.ripe.net",
    "217.0.0.0/8": "whois.ripe.net",
    "218.0.0.0/8": "whois.apnic.net",
    "219.0.0.0/8": "whois.apnic.net",
    "220.0.0.0/8": "whois.apnic.net",
    "221.0.0.0/8": "whois.apnic.net",
    "222.0.0.0/8": "whois.apnic.net",
    }
_WHOIS_IPV6 = {
    #
    # Sub-TLA Assignments
    # see http://www.iana.org/assignments/ipv6-tla-assignments
    #
    "^2001:0?[01][A-F0-9][A-F0-9]:.+": "whois.iana.org",
    "^2001:0?[23][A-F0-9][A-F0-9]:.+": "whois.apnic.net",
    "^2001:0?[45][A-F0-9][A-F0-9]:.+": "whois.arin.net",
    "^2001:0?[67][A-F0-9][A-F0-9]:.+": "whois.ripe.net",
    "^2001:0?[89][A-F0-9][A-F0-9]:.+": "whois.ripe.net",
    "^2001:0?[AB][A-F0-9][A-F0-9]:.+": "whois.ripe.net",
    "^2001:0?[CD][A-F0-9][A-F0-9]:.+": "whois.apnic.net",
    "^2001:0?[EF][A-F0-9][A-F0-9]:.+": "whois.apnic.net",
    "^2001:1[23][A-F0-9][A-F0-9]:.+": "whois.lacnic.net",
    "^2001:1[45][A-F0-9][A-F0-9]:.+": "whois.ripe.net",
    "^2001:1[67][A-F0-9][A-F0-9]:.+": "whois.ripe.net",
    "^2001:1[89][A-F0-9][A-F0-9]:.+": "whois.arin.net",
    "^2001:1[AB][A-F0-9][A-F0-9]:.+": "whois.ripe.net",
    "^2001:1[CD][A-F0-9][A-F0-9]:.+": "whois.ripe.net",
    "^2001:1[EF][A-F0-9][A-F0-9]:.+": "whois.ripe.net",
    "^2001:2[A-F0-9][A-F0-9][A-F0-9]:.+": "whois.ripe.net",
    "^2001:3[A-B0-9][A-F0-9][A-F0-9]:.+": "whois.ripe.net",
    "^2001:4[01][A-F0-9][A-F0-9]:.+": "whois.ripe.net",
    "^2001:4[23][A-F0-9][A-F0-9]:.+": "whois.arin.net",
    "^2001:4[45][A-F0-9][A-F0-9]:.+": "whois.apnic.net",
    "^2001:4[67][A-F0-9][A-F0-9]:.+": "whois.ripe.net",
    }
_WHOIS_TLD = {
    #
    # Pseudo-ccTLDs must be listed above gTLDs
    #
    "\\.ae\\.org$": "whois.centralnic.net",
    "\\.br\\.com$": "whois.centralnic.net",
    "\\.cn\\.com$": "whois.centralnic.net",
    "\\.de\\.com$": "whois.centralnic.net",
    "\\.eu\\.com$": "whois.centralnic.net",
    "\\.eu\\.org$": "whois.eu.org",
    "\\.gb\\.com$": "whois.centralnic.net",
    "\\.gb\\.net$": "whois.centralnic.net",
    "\\.hu\\.com$": "whois.centralnic.net",
    "\\.jpn\\.com$": "whois.centralnic.net",
    "\\.kr\\.com$": "whois.centralnic.net",
    "\\.no\\.com$": "whois.centralnic.net",
    "\\.qc\\.com$": "whois.centralnic.net",
    "\\.ru\\.com$": "whois.centralnic.net",
    "\\.sa\\.com$": "whois.centralnic.net",
    "\\.se\\.com$": "whois.centralnic.net",
    "\\.se\\.net$": "whois.centralnic.net",
    "\\.uk\\.com$": "whois.centralnic.net",
    "\\.uk\\.net$": "whois.centralnic.net",
    "\\.us\\.com$": "whois.centralnic.net",
    "\\.uy\\.com$": "whois.centralnic.net",
    "\\.web\\.com$": "whois.centralnic.net",
    "\\.za\\.com$": "whois.centralnic.net",

    "\\.ac$": "whois.nic.ac",
    "\\.ae$": "whois.uaenic.ae",
    "\\.aero$": "whois.aero",
    "\\.ag$": "whois.nic.ag",
    "\\.ai$": "whois.offshore.ai",
    "\\.al$": "whois.ripe.net",
    "\\.am$": "whois.amnic.net",
    "\\.ar$": "www.nic.ar",
    "\\.as$": "whois.nic.as",
    "\\.at$": "whois.nic.at",
    "\\.asn\\.au$": "whois.ausregistry.net.au",
    "\\.com\\.au$": "whois.ausregistry.net.au",
    "\\.id\\.au$": "whois.ausregistry.net.au",
    "\\.net\\.au$": "whois.ausregistry.net.au",
    "\\.org\\.au$": "whois.ausregistry.net.au",
    "\\.au$": "whois.aunic.net",
    "\\.org\\.au$": "whois.ausregistry.net.au",
    "\\.au$": "whois.aunic.net",
    "\\.az$": "whois.ripe.net",
    "\\.ba$": "whois.ripe.net",
    "\\.be$": "whois.dns.be",
    "\\.bg$": "whois.register.bg",
    "\\.bi$": "www.nic.bi",
    "\\.biz$": "whois.neulevel.biz",
    "\\.bm$": "rwhois.ibl.bm 4321",
    "\\.br$": "whois.nic.br",
    "\\.bv$": "whois.ripe.net",
    "\\.by$": "whois.ripe.net",
    "\\.bz$": "whois.belizenic.bz",
    "\\.ca$": "whois.cira.ca",
    "\\.cat$": "whois.cat",
    "\\.cc$": "whois.nic.cc",
    "\\.cd$": "whois.nic.cd",
    "\\.cg$": "www.nic.cg",
    "\\.ch$": "whois.nic.ch",
    "\\.ck$": "whois.nic.ck",
    "\\.cl$": "whois.nic.cl",
    "\\.edu\\.cn$": "whois.edu.cn",
    "\\.cn$": "whois.cnnic.net.cn",
    "\\.com$": "whois.verisign-grs.com",
    "\\.coop$": "whois.nic.coop",
    "\\.cx$": "whois.nic.cx",
    "\\.cy$": "whois.ripe.net",
    "\\.cz$": "whois.nic.cz",
    "\\.de$": "whois.denic.de",
    "\\.dk$": "whois.dk-hostmaster.dk",
    "\\.do$": "whois.nic.do",
    "\\.dz$": "whois.ripe.net",
    "\\.ec$": "www.nic.ec",
    "\\.edu$": "whois.educause.net",
    "\\.ee$": "whois.eenet.ee",
    "\\.eg$": "whois.ripe.net",
    "\\.es$": "www.nic.es",
    "\\.eg$": "whois.ripe.net",
    "\\.es$": "www.nic.es",
    "\\.eu$": "whois.eu",
    "\\.fi$": "whois.ficora.fi",
    "\\.fj$": "whois.usp.ac.fj",
    "\\.fm$": "www.dot.fm",
    "\\.fo$": "whois.ripe.net",
    "\\.fr$": "whois.nic.fr",
    "\\.gi$": "www.nic.gi",
    "\\.gov$": "whois.nic.gov",
    "\\.gg$": "whois.isles.net",
    "\\.gm$": "whois.ripe.net",
    "\\.gr$": "whois.ripe.net",
    "\\.gs$": "whois.adamsnames.tc",
    "\\.gt$": "www.gt",
    "\\.hk$": "whois.hkdnr.net.hk",
    "\\.hm$": "whois.registry.hm",
    "\\.hr$": "www.dns.hr",
    "\\.hu$": "whois.nic.hu",
    "\\.id$": "whois.idnic.net.id",
    "\\.ie$": "whois.domainregistry.ie",
    "\\.il$": "whois.isoc.org.il",
    "\\.in$": "whois.inregistry.in",
    "\\.info$": "whois.afilias.info",
    "\\.int$": "whois.iana.org",
    "\\.io$": "www.io.io",
    "\\.ir$": "whois.nic.ir",
    "\\.im$": "www.nic.im",
    "\\.is$": "whois.isnic.is",
    "\\.it$": "whois.nic.it",
    "\\.je$": "whois.isles.net",
    "\\.jp$": "whois.jprs.jp",
    "\\.kg$": "whois.domain.kg",
    "\\.kr$": "whois.krnic.net",
    "\\.kz$": "whois.nic.kz",
    "\\.la$": "whois.nic.la",
    "\\.lb$": "cgi.aub.edu.lb",
    "\\.li$": "whois.nic.li",
    "\\.lk$": "whois.nic.lk",
    "\\.lt$": "whois.domreg.lt",
    "\\.lk$": "whois.nic.lk",
    "\\.lt$": "whois.domreg.lt",
    "\\.lu$": "whois.dns.lu",
    "\\.lv$": "whois.nic.lv",
    "\\.ma$": "whois.ripe.net",
    "\\.mil$": "whois.nic.mil",
    "\\.mk$": "whois.ripe.net",
    "\\.mm$": "whois.nic.mm",
    "\\.mobi$": "whois.dotmobiregistry.net",
    "\\.ms$": "whois.adamsnames.tc",
    "\\.mt$": "www.um.edu.mt",
    "\\.museum$": "whois.museum",
    "\\.mw$": "www.tarsus.net",
    "\\.mx$": "whois.nic.mx",
    "\\.my$": "whois.mynic.net.my",
    "\\.na$": "whois.na-nic.com.na",
    "\\.name$": "whois.nic.name",
    "\\.net$": "whois.verisign-grs.com",
    "\\.ng$": "whois.rg.net",
    "\\.nl$": "whois.domain-registry.nl",
    "\\.no$": "whois.norid.no",
    "\\.nu$": "whois.nic.nu",
    "\\.nz$": "whois.srs.net.nz",
    "\\.org$": "whois.publicinterestregistry.net",
    "\\.pe$": "whois.nic.pe",
    "\\.pk$": "pknic.net.pk",
    "\\.pl$": "whois.dns.pl",
    "\\.pro$": "whois.registrypro.pro",
    "\\.pt$": "whois.dns.pt",
    "\\.pw$": "whois.nic.pw",
    "\\.ro$": "whois.rotld.ro",
    "\\.ru$": "whois.ripn.net",
    "\\.rw$": "www.nic.rw",
    "\\.sa$": "saudinic.net.sa",
    "\\.se$": "www.nic-se.se",
    "\\.sg$": "whois.nic.net.sg",
    "\\.sh$": "whois.nic.sh",
    "\\.si$": "whois.arnes.si",
    "\\.sj$": "whois.ripe.net",
    "\\.sk$": "whois.ripe.net",
    "\\.sj$": "whois.ripe.net",
    "\\.sk$": "whois.ripe.net",
    "\\.sm$": "whois.ripe.net",
    "\\.sr$": "whois.register.sr",
    "\\.st$": "whois.nic.st",
    "\\.su$": "whois.ripn.net",
    "\\.tc$": "whois.adamsnames.tc",
    "\\.tf$": "whois.adamsnames.tc",
    "\\.tg$": "www.nic.tg",
    "\\.th$": "whois.thnic.net",
    "\\.tj$": "whois.nic.tj",
    "\\.tk$": "whois.dot.tk",
    "\\.tm$": "whois.nic.tm",
    "\\.tn$": "whois.ripe.net",
    "\\.to$": "whois.tonic.to",
    "\\.tr$": "whois.metu.edu.tr",
    "\\.tt$": "www.nic.tt",
    "\\.tv$": "whois.tv",
    "\\.tw$": "whois.twnic.net",
    "\\.ua$": "whois.com.ua",
    "\\.ug$": "whois.co.ug",
    "\\.ac\\.uk$": "whois.ja.net",
    "\\.gov\\.uk$": "whois.ja.net",
    "\\.uk$": "whois.nic.uk",
    "\\.fed\\.us$": "whois.nic.gov",
    "\\.us$": "whois.nic.us",
    "\\.com\\.uy$": "dns.antel.net.uy",
    "\\.uy$": "www.rau.edu.uy",
    "\\.uz$": "www.noc.uz",
    "\\.va$": "whois.ripe.net",
    "\\.ve$": "rwhois.nic.ve 4321",
    "\\.vi$": "www.nic.vi",
    "\\.vg$": "whois.adamsnames.tc",
    "\\.vn$": "www.vnnic.net.vn",
    "\\.vu$": "www.vunic.vu",
    "\\.ws$": "whois.worldsite.ws",
    "\\.yu$": "whois.ripe.net",
    "\\.ac\\.za$": "whois.ac.za",
    "\\.org\\.za$": "rwhois.org.za 4321",
    "\\.co\\.za$": "whois.co.za",
}
_WHOIS_BLOCK = {
    "^!?NET\\(BLK\\)?\\(-[A-Z0-9]+\\)+$": "whois.arin.net",
    
    "^COCO-[0-9]+$": "whois.corenic.net",
    "^CORE-[0-9]+$": "whois.corenic.net",
    "^COHO-[0-9]+$": "whois.corenic.net", 

    ".*-RIPE$": "whois.ripe.net",
    ".*-MNT$": "whois.ripe.net",
    ".*-ARIN$": "whois.arin.net",
    ".*-AP$": "whois.apnic.net",
    ".*-ORG$": "whois.internic.net",
    ".*-DOM$": "whois.internic.net",
    ".*-NORID$": "whois.norid.no",
    ".*-GANDI$": "whois.gandi.net",
    ".*-AU$": "whois.aunic.net",
    ".*-CKNIC": "whois.nic.ck",
    ".*-IDNIC$": "whois.idnic.net.id",
    ".*-KG$": "whois.domain.kg",
    ".*-NICAT$": "whois.nic.at",
    ".*-CZ$": "whois.nic.cz",
    ".*-NICIR$": "whois.nic.ir",
    ".*-UYNIC$": "www.rau.edu.uy",
    ".*-ITNIC$": "whois.nic.it",
    ".*-FRNIC$": "whois.nic.fr",
    ".*-LACNIC$": "whois.lacnic.net",
    ".*-DK$": "whois.dk-hostmaster.dk",
    ".*-SA$": "saudinic.net.sa",
}

# compile maps
WHOISMAP = {}
WHOISMAP.update(whoisMapRe(_WHOIS_AS))
WHOISMAP.update(whoisMapIPv4(_WHOIS_IPV4))
WHOISMAP.update(whoisMapRe(_WHOIS_IPV6))
WHOISMAP.update(whoisMapRe(_WHOIS_TLD))
WHOISMAP.update(whoisMapRe(_WHOIS_BLOCK))

# vim:ts=4:sw=4:et:
